Spring JPA Ⅺ 自给自足之Query详解

您所在的位置:网站首页 spring boot jpa分页查询 Spring JPA Ⅺ 自给自足之Query详解

Spring JPA Ⅺ 自给自足之Query详解

2023-05-12 04:44| 来源: 网络整理| 查看: 265

前言

有些同学在使用 JPA 自带的一些接口时,觉得很不自在,浑身不得劲。尤其碰到那些较为复杂的情况,更是心中愤恨:几行 SQL 就能解决的问题,为啥需要这么麻烦呢?别急,JPA 早就为大家准备了自由发挥的空间,那就是注解 @Query,今天就跟大家一起探讨下此注解的用法。

源码 @Documented public @interface Query { /** * 指定执行的 JPQL 的查询语句 */ String value() default ""; /** * 指定查询 count 的 JPQL 语句;如果不指定将根据 query ⾃动⽣成 */ String countQuery() default ""; /** * 根据哪个字段来 count,⼀般默认即可 */ String countProjection() default ""; /** * 是否使用原生SQL语句;默认为false */ boolean nativeQuery() default false; /** * 给 query 设置一个 name;如果没有,则使用{$domainClass}.${queryMethodName}命名 */ String name() default ""; /** * 给 count 的 query 设置一个name;如果没有,则使用 {$domainClass}.${queryMethodName}.count 命名 */ String countName() default ""; } 复制代码 JPQL 与 SQL 的区别

JPQL(Java Presistence Query Language) 是 java 持久性查询语言,是面向对象的查询语言,因此它可以完全理解继承、多态和关联等特征。而且 JPQL 内置了大量函数,极大地方便了 JPQL 查询的功能。当然 JPQL 底层依然是基于 SQL 的,但 JPQL 到 SQL 的转换无须开发者关心,JPQL 解析器会负责完成这种转换,并负责执行这种转换的 SQL 语句来更新数据库。 SQL 是面向关系数据库的查询语言,因此 SQL 操作的对象是数据表、数据列;而 JQPL 操作的对象是实体对象,对象属性。

代码对比

JPQL:

//面向对象的 JPQL 语句,其中 User 是实体类 select u from User u 复制代码

SQL:

//原生 SQL 语句,其中 t_user 是表名 select * from t_user 复制代码 基本用法 一、JPQL 写法 Dao 层代码 @Query(value = "select u from User u where u.id = ?1") User findUserByQuery(int id); 复制代码

控制台打印如下:

Hibernate: select user0_.id as id1_2_, user0_.age as age2_2_, user0_.name as name3_2_ from user user0_ where user0_.id=? 复制代码

小贴士

查询语句中的 ? 后面跟的数字代表的是入参的索引(从1开始)

除了这个种写法外,还有一种 @Param 的用法:他是使用 :参数 的方式进行指定查询条件。

个人比较推荐第二种方式,因为这种方式比较清晰明朗,而且有助于后期维护和代码重构。

@Query(value = "select u from User u where u.id = :id") User findUserByQuery(@Param("id") int id); 复制代码

控制台打印如下:

Hibernate: select user0_.id as id1_2_, user0_.age as age2_2_, user0_.name as name3_2_ from user user0_ where user0_.id=? 复制代码 二、SQL 写法 Dao 层代码 @Query(value = "select * from user where id = ?1", nativeQuery = true) User findUserByQuery(int id); 复制代码

控制台打印如下:

Hibernate: select * from user where id = ? 复制代码 排序用法 Dao 层代码 @Query(value = "select u from User u") List findAllSortByQuery(Sort sort); 复制代码 Control 层代码 @GetMapping("findAllSortByQuery") public List findAllSortByQuery(String sortPara){ Sort sort = Sort.by( Sort.Direction.DESC, sortPara); return userService.findAllSortByQuery(sort); } 复制代码

控制台打印如下:

Hibernate: select user0_.id as id1_2_, user0_.age as age2_2_, user0_.name as name3_2_ from user user0_ order by user0_.age desc 复制代码

小贴士

nativeQuery 是不支持 Sort 参数排序的。 sort 的排序用法,我们在之前的文章中已经分析过了,详情请见 sort 用法

分页用法 Dao 层代码 @Query(value = "select u from User u") Page findAllPageByQuery(Pageable pageable); 复制代码 Control 层代码 @GetMapping("findAllPageByQuery") public Page findAllPageByQuery(){ Pageable pageable = PageRequest.of(1, 2); return userService.findAllPageByQuery(pageable); } 复制代码

控制台打印如下:

Hibernate: select user0_.id as id1_2_, user0_.age as age2_2_, user0_.name as name3_2_ from user user0_ limit ?, ? Hibernate: select count(user0_.id) as col_0_0_ from user user0_ 复制代码

小贴士

pageable 的分页用法,我们在之前的文章中也已经分析过了,详情请见 pageable 用法

countQuery 的使用

countQuery 一般用于分页查询,用来查找页面元素的总个数,其结果用于填充返回的 Page 的 totalCount 属性。

Dao 层代码 @Query(value = "select * from user where age = 22", countQuery = "select count(*) from user where age = 22", nativeQuery = true) Page findAllPageByQuery(Pageable pageable); 复制代码

控制台打印如下:

Hibernate: select * from user where age = 22 limit ?, ? Hibernate: select count(*) from user where age = 22 复制代码

小贴士

一般情况下 countQuery 不需要配置,系统会根据 query 自动生成一个 count 查询,其结果为返回的 page 对象 totalCount 属性。

最终总结

其实 @Query 中用的最多的就是 value、nativeQuery、countQuery 的值,其他的基本用不到。还有就是在实际项目中,我们如果使用 JPA 的话,一般都会遵循下面三个原则:

能⽤⽅法名表示的,尽量⽤⽅法名表示,因为这样语义清晰、简单快速,基本上只要编译通过,⼀定不会有问题 能⽤ @Query ⾥⾯的 JPQL 表示的,就⽤ JPQL,这样与 SQL ⽆关,万⼀哪天换数据库了,基本上代码不⽤改变 最后实在没有办法了,可以选择 nativeQuery 写原始 SQL


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3